package com.woniuxy.yoga.progress.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.yoga.commons.core.model.Result;
import com.woniuxy.yoga.commons.redis.util.rediskeyutil.CourseRedisKeyUtil;
import com.woniuxy.yoga.progress.client.OrderClient;
import com.woniuxy.yoga.progress.dao.model.Pricard;
import com.woniuxy.yoga.progress.dao.mapper.PricardMapper;
import com.woniuxy.yoga.progress.dao.model.Subcard;
import com.woniuxy.yoga.progress.model.exception.ProgressException;
import com.woniuxy.yoga.progress.model.exception.ProgressExceptionCode;
import com.woniuxy.yoga.progress.model.form.GetUnfinishPriByIdForm;
import com.woniuxy.yoga.progress.model.param.CreatePriCardParam;
import com.woniuxy.yoga.progress.service.PricardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 私教课流程表 服务实现类
 * </p>
 *
 * @author 韦用文,刘存益,郎腾霄
 * @since 2023年11月28日
 */
@Service
public class PricardServiceImpl extends ServiceImpl<PricardMapper, Pricard> implements PricardService {

    @Autowired
    private PricardMapper pricardMapper;

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 创建私教课进度表
     * @param param 创建私教课进度表参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPriCard(CreatePriCardParam param) {
        //查重
        QueryWrapper<Pricard> wrapper = new QueryWrapper<>();
        wrapper.eq("order_num",param.getOrderNum());
        Pricard pricard = pricardMapper.selectOne(wrapper);
        if (pricard!=null) throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_CARD_REPEAT);
        //创建私教课进度对象
        Pricard card = new Pricard();
        card.setCoachId(param.getCoachId());
        card.setOrderNum(param.getOrderNum());
        card.setUserId(param.getUserId());
        card.setPricardCount(param.getPricardCount());
        card.setPricardUse(0);
        pricardMapper.insert(card);
    }

    /**
     * 完成私教卡
     * @param pricardId 私教卡id
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void finishPricard(Integer pricardId) {
        //查询课程
        Pricard pricard = pricardMapper.selectById(pricardId);
        if (pricard == null) throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_CARD_NOT_EXIST);
        //查询课程是否完成
        if (!Objects.equals(pricard.getPricardCount(), pricard.getPricardUse()))
            throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_PRI_CARD_NOT_USED);
        //修改订单状态
        Result<String> result = orderClient.completeOrder(pricard.getOrderNum());
        if (result.getCode()!=200) throw new ProgressException(result.getCode(),result.getMessage());
        //修改
        pricard.setCompleteTime(DateUtil.format(new Date(System.currentTimeMillis()),"yyyy-MM-dd HH:mm:ss"));
        pricardMapper.updateById(pricard);
    }

    /**
     * 查询未完成私教卡
     * @param userId userId
     * @return Pricard
     */
    @Override
    public Pricard getUnfinishPri(Integer userId) {
        //创建查询
        QueryWrapper<Pricard> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",userId);
        wrapper.isNull("complete_time");
        Pricard pricard = pricardMapper.selectOne(wrapper);
        if (pricard==null) throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_CARD_NOT_EXIST);
        return pricard;
    }

    /**
     * 私教进度次数加一
     * @param pricardId 私教卡id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSubCardCount(Integer pricardId) throws Exception {
        //创建单锁
        RLock lock = redissonClient.getFairLock(CourseRedisKeyUtil.lockCurrentCountByCourseId(pricardId));
        boolean isLock = lock.tryLock(10, TimeUnit.SECONDS);
        try {
            if (!isLock){
                throw new Exception("服务器繁忙请稍后再试");
            }
            //查询进度
            Pricard pricard = pricardMapper.selectById(pricardId);
            if (pricard==null) throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_CARD_NOT_EXIST);
            if (pricard.getPricardUse()+1>pricard.getPricardCount())
                throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_PRI_CARD_COUNT_STACK);
            if (pricard.getPricardUse()+1==pricard.getPricardCount())
                this.finishPricard(pricardId);
            //次数+1
            pricard.setPricardUse(pricard.getPricardUse()+1);
            pricardMapper.updateById(pricard);
        }finally {
            //判断是否是自己的锁 并且还未释放
            if (lock.isLocked()){
                lock.unlock();
            }
        }
    }

    /**
     * 查询未完成私教卡
     * @param form form
     * @return Pricard
     */
    @Override
    public Integer getUnfinishPriById(GetUnfinishPriByIdForm form) {
        //创建查询
        QueryWrapper<Pricard> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",form.getUserId());
        wrapper.eq("coach_id",form.getCoachId());
        wrapper.isNull("complete_time");
        Pricard pricard = pricardMapper.selectOne(wrapper);
        if (pricard==null) throw new ProgressException(ProgressExceptionCode.PROGRESS_EXCEPTION_CODE_CARD_NOT_EXIST);
        return pricard.getPricardId();
    }
}
